package leetcode_100;

public class SearchinRotatedSortedArray_33 {

	public static void main(String[] args) {
		SearchinRotatedSortedArray_33 test=new SearchinRotatedSortedArray_33();
		System.out.println(test.search1(new int[] {1,2,3,4,5,6}, 4));
		//System.out.println(search(new int[] {1,3},1));
		//System.out.println(search(new int[] {0,1,2,4,5,6,7},4));

	}
	
	 public int search1(int[] nums, int target) {
		 if(nums.length==0) return -1;
		 int left=0,right=nums.length-1;
		 if(nums[right]<nums[left]) {
			 while(left<right) {
				 if(nums[left]==target) return left;
				 if(nums[right]==target) return right;
				 int mid=left+((right-left)>>1);
				 if(nums[mid]==target) return mid;
				 if(nums[mid]<nums[left]) right=mid;
				 else if(nums[mid]>nums[right]) left=mid+1;
				 else right=left;
			 }
			 if(nums[nums.length-1]>target&&nums[left]<target) {
				 right=nums.length-1;
			 }
			 else if(nums[0]<target&&left>0&&nums[left-1]>target) {
				 right=left-1;
				 left=0;
			 }
			 else return nums[left]==target?left:-1;
		 }
		 while(left<right) {
			 int mid=left+((right-left)>>1);
			 if(nums[mid]==target) return mid;
			 else if(nums[mid]>target) right=mid-1;
			 else left=mid+1;
		 }
		 return  nums[left]==target?left:-1;
	 }
	
	
	public static int search(int[] nums, int target) {

        if (nums != null && nums.length > 0) {

            // 找最小元素对应的下标
            int minIndex = searchMinIndex(nums, 0, nums.length - 1);

            // 整个数组全局有序
            if (minIndex == 0) {
                return binarySearch(nums, 0, nums.length - 1, target);
            } 
            // 有两个局部有序区间,  如 4 5 6 7 8 9 0 1 2 3 
            else {
                // 恬好和后一个有序区间的最后一个元素相等，返回对应的下标
                if (nums[nums.length - 1] == target) {
                    return nums.length -1;
                } 
                // target可能在后一个有序区间中
                else if (nums[nums.length - 1] > target) {
                    return binarySearch(nums, minIndex, nums.length - 1, target);
                } 
                // target可能是前一个有序区间中
                else {
                    return binarySearch(nums, 0, minIndex -1, target);
                }
            }
        }

        return -1;
    }

    /**
     * 二分搜索
     *
     * @param nums   数组
     * @param start  起始位置
     * @param end    结束位置
     * @param target 搜索目标
     * @return 匹配元素的下标
     */
    public static int binarySearch(int[] nums, int start, int end, int target) {

        int mid;
        while (start <= end) {
            mid = start + ((end - start) >> 1);

            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] > target) {
                end = mid - 1;
            } else {
                start = mid + 1;
            }
        }

        return -1;
    }

    /**
     * 找最小元素的下标
     *
     * @param nums  数组
     * @param start 起始位置
     * @param end   结束位置
     * @return 最小元素的下标
     */
    public static int searchMinIndex(int[] nums, int start, int end) {

        int mid;
        while (start < end) {
            mid = start + ((end - start) >> 1);
            // 后一个数比前个数小就找到了
            if (nums[mid] > nums[mid + 1]) {
                return mid + 1;
            }
            // 说明中间值在第一个有序的数组中
            else if (nums[mid] > nums[start]) {
                start = mid;
            }
            // 说明中间值在第二个有序的数组中
            else {
                end = mid;
            }
        }

        // 说明整个数组是有序的
        return 0;
    }
}
